package com.yiboshi.rehrs.config;

import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.yiboshi.rehrs.common.Decrypt;
import com.yiboshi.rehrs.common.VarConstant;
import com.yiboshi.rehrs.common.ZhongConfig;
import com.yiboshi.rehrs.helper.ZhongConfigHelper;
import com.yiboshi.rehrs.param.ZhongReq;
import com.yiboshi.rehrs.param.ZhongRes;
import com.yiboshi.rehrs.util.*;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.time.LocalDate;
import java.util.*;


@Aspect
@Configuration//定义一个切面
@Slf4j
public class ControllerAspect {
    private static final Logger logger = LoggerFactory.getLogger(ControllerAspect.class);
    static String[] a = "BYTES,MAX_VALUE,MIN_VALUE,SIZE,serialVersionUID".split(",");
    static Set<String> fieldSet = new HashSet<>(Arrays.asList(a));


    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Value("${spring.profiles.active:}")
    String profile;

    @Autowired
    ZhongConfigHelper zhongConfigHelper;

    //Executor providerSimpleAsync = ExeUtil.buildSimpleExecutor("logrecord-thread");
    // 定义切点Pointcut
    @Pointcut("execution(* com..*.*Controller.*(..))")
    public void executionController() {

    }

    byte[] aesKeyBytesSm = "0UYy5o244bill9zc3mise29ev9query_".getBytes();
    String aesIvStrSm = "d60UYftxsgshnxj8";
    String signStrSm = "Build/PQ3A((sf@Jfs!";


    @Around("executionController()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        HttpServletRequest request = WebUtils.getRequest();
        String requestURI = request.getRequestURI();
        Object[] args = pjp.getArgs();
        if( requestURI.contains("/smf/user")){
            //return doSmAround(pjp,args);
        }
        boolean isSm = requestURI.contains("/smf/");

        ZhongConfig localConfig = zhongConfigHelper.getLocalConfig();
        byte[] aesKeyBytes =isSm?aesKeyBytesSm: localConfig.getAesKeyBytes();
        String aesIvBytes =isSm?aesIvStrSm: localConfig.getAesIvStr();
        String signStr =isSm?signStrSm: localConfig.getSignStr();
        boolean security = requestURI.contains("/api/user")||requestURI.contains("/smf/user");
        if(request!=null&&args!=null&&args.length==2&&security){
            //入参解密
            Object versionObj = args[0];
            if(versionObj==null){
                return ZhongRes.fail("5000");
            }
            if(!NumberUtil.isNumber(versionObj.toString())){
                return ZhongRes.fail("5001");
            }
            if(args[1] instanceof ZhongReq){
                ZhongReq zhongReq = ( ZhongReq)args[1];
                String data = zhongReq.getData();
                String sign = zhongReq.getSign();
                MethodSignature methodSignature = (MethodSignature)pjp.getSignature();
                Decrypt annotation = methodSignature.getMethod().getAnnotation(Decrypt.class);
                boolean needDecrypt = annotation==null||annotation.value();
               if(StrUtils.isNotBlank(data)&&needDecrypt){
                    String decrypt = MyAESUtil.decryptAES(data, aesKeyBytes, aesIvBytes);
                    if(StrUtils.isBlank(decrypt)){
                        log.info("5010,解密data错误");
                        //return ZhongRes.fail("5010,解密data错误");
                        return null;
                    }
                    String sign_new = MD5.encode(decrypt + signStr);
                    if(!sign_new.equalsIgnoreCase(sign)){
                        log.info("5011,签名sign错误");
                        //return ZhongRes.fail("5011,签名sign错误");
                        return null;
                    }
                    ZhongReq zhongReq1 = JacksonUtils.toBean(decrypt, ZhongReq.class);
                   BeanUtils.copyProperties(zhongReq1,zhongReq);
                  /* Gson gson = new GsonBuilder()
                           .setDateFormat("yyyy-MM-dd HH:mm:ss")
                           .create();
                   //对结果进行转换
                   ResponseDataModel<?> result = gson.fromJson(body, new ParameterizedTypeImpl(ResponseDataModel.class, new Type[]{type}));*/

                   //log.info("req uri:{} data:{}",request.getRequestURI(),decrypt);
                   zhongReq.setOriginData(decrypt);
                   //zhongReq.setReqObj();
                }
            }
        }
        Object result = pjp.proceed();
        if(result==null){
            return null;
        }
        boolean resSecurity = requestURI.contains("/api/user")||requestURI.contains("/smf/");
        if(result instanceof ZhongRes && resSecurity){
            ZhongRes zhongRes = (ZhongRes)result;
            Object obj = zhongRes.getObj();
            if(obj!=null){
                String jsonObj = JacksonUtils.toString(obj);
                //log.info("res obj:{}",jsonObj);
                String sign = MD5.encode(jsonObj + signStr);
                String encrypt = MyAESUtil.encrypt(jsonObj, aesKeyBytes, aesIvBytes);
                zhongRes.setData(encrypt);
                zhongRes.setSign(sign);
                if(!RehrsSystemConfig.isDev()){
                    zhongRes.setObj(null);
                }
            }
        }
        return result;

    }

    private Object doSmAround(ProceedingJoinPoint pjp, Object[] args) {
        if(args.length>0){
            if(args[0] instanceof JSONObject){

            }
        }

        return null;
    }


    public static void main(String[] args) {
        //"aesKeyStr": "ypw5ky24f4bwmdt9zc3mece29ev9qudz",
        //        		"aesIvStr": "d6guntxsgshnxjww",
        String data = "C752BCF8190F8A9A87E7C7325570F0A962E5AF23C4B7AB2AC4132A24CC5C40F03301832C54AFC5CB4E5020FFFD4D61D98C11A424B5B4E16A48A4B74CF6D80BD8D7B3FCDD6CAD8DCC755BFE74DB4086B0BC6658609A0D8AA8B8BFEF860CE717B8D00EA1A875CC6BBACE87B5C6167BCF1FD3199343251ED9991EA8B3851BA4B6B82B23B474FBCCA35A09F0A38B8336C10BAAD7EA5615F2FA0E04728ADC7D5D2C8B554E2CA9243396E3D171B7C3812EAEA6E28A30A75713B317BDC50A5F026414FC2F3CE375029876F8CCE3B5421C9AF13F375821FA85D21B090A23E552AB3A3AF5B768F639F3A78E7AE7617FFE3D011E5494499993453AB42371CE2E06A2F2EB2C0F3520E173993ED3494CBF69DE69D929CA962119335FAE158A5D33D1B9E83699B0FE01C32ECEA25CBAEA60F369260A700D49A809D294BED8970A0D3EB1A659546B82EAC815100F9AD9074A0D64ADC18A7248076ED0B5DDE5A911F289C45440F9EDF1395CEB90ADCEA9A6A04152801D08FCB4490591029D4A0988B61D7581F1EE08FA94906A943F8FC0FC1FF98B553519D64BB176D07A7C8B0B3263A415A6498A64056EF3922AE0CF0A6A9D845ED59DBC6B474792CBCD32FBE7B890EBC08345EFB54E8C21BE6006D029A114A98D697B7D2A03D097DF483099535A3D432794C108705A459B99F3785059037D3AEF016F4906A1F840FBD0497A10B9483C59A96620DFE8288125912EE015D5881B06973AA757A125B84CFD70339D8C32C7A60A93EB1621F4BD15A85035762EFFBD3F96B74E71221CAC6412EB46493F47E2E0FFB64B1EEFCBC7FEEF7F5083AC607C085E65D2EEC35634E463D62DD09A782E7773DC124770B3600BEEB0E9D5C89C3478E5792C8766BDEE4FA3D8B2A01867B48FC07DA3F36EB25C65A555F9B76E171192B96FB53F3E155CF0666C2EAE0ACE3B288434D65599295C4176DB3AD28D74E2A770145CF153D643D3C6C2B138437FDC7CC2046F5E21EB4F77417A1BA6EF3ED4E6502B33ECDD286837DD92540DE1092767513FB41E601C22624752F514306E0D127D63E3EF97F6A8A6D54BC40D33BD332F28FA24596E2EF8A69910629D886C9ABDFFA041368BAD2B6780B1A4E5E2282793FFBBA14C30A911F10BC7F6AEB3390A846BAFC649DAC916778CB6D3F0AF52B5D24BCF996A426FA003FEFB5B96A24F987A3F65CE718EDDDF203D6011DBCA7A6B612B3062A8D5921B88CAB9AE43CA89DD716C736E57A4C12296E4598F0347DADEFBC8CEEB01E2BA3B7AF5C11CE9A7F53C703AD3B04E8F04CD709234FA3B0EE73E358CF61584122F4F3FE228950BDE631E7913099FC3EB8A4C415B6E945CA263C28FECE48C2ED009E39AD98FCCFEE4C8FFDA5E70D439CFF23CCCECCB09BBE4FF5CAE5D894DE4CFCF97AA51AC0B279CA95C2C90BA9DE915C136BA5A8B80C50F8978AED8F938724B57CD14C01EEA8B17643CFDF6B71E0C280094A8AF984E5C0337E54109512130ADE73BA84CBBDD73690E80FA05FC9ABDCC5B5D4B096C1E6621916EFE7F109915685E633BF395F4936627B100A5A3CA83E9E8DB82C0B75C4707A3BB990348EFB1D65E6A438425F4453ED32858A7F07D140C5207DB9758D90806046C5CCD8C4CB26F456F2D277F41D143B13B5E65756EC46B28BD0AD78E51BCAE6B31A8A37DEBDDF2AF92ABE872737BB6920C9CB5C97C1C67E4963E4318D53D4976FA44998FF6BFBC1B449F121A7D51B7F047F1BBFF06A0BDC6CD9109D9B36BF380A29AFEB060515A283851C23DD48FF6D95F84C1C63F066B6BD5F45B0E6A2C5CAE28349951C66D329225A3C03746A58CAB4C9F20996B0C1EFB75E8266978D7703D2DAF86BF55DF419119B299B429EB3563C52E96D653F42934FB86369FF41B01DEFB6F932CFE25A378EFC8E5F4BD084DACC46CF2139DA6FBD7559039BCDCB8BFB0477510851CC1557A0A1104C5B2FB67056EB9B5F9AD8A3B6C73F057D1F93EA4072842BB85ECCD36A3D428D3D4CCF9ECFF0BFD5D5C41E86470631725A9D58756167BBFA904E9F201A2184894DF71C871622543FACA854F9AEBD3AFEB79C537113878052D921F14FD5CE3F6E265249FC25CA54932FF9081E03AECC65F3D03A7F73FDB7B8FD7BD5C922AD648DDB339A14D45688B602C00256CAEFFA914F50C754C84A5BF4D800A138FFE8F9E68696A87C2654A60C9DE8240E70593A7F0907CF208AF43A6B2F5C95FBBFF874AE9C20AC987AD536BACE00E54CE742256415AEC5337B676DBDADC6D980CED6398D935946B706500EB3056A13A5BCE6D8B6B1F691D7685967BA4D2609C7305465B0DD3CCB51A74068109D9ACF35B327F1F14B67BCC64DAEF6A11C236FD839E59700C9A670C817FC14C2C009011126BA51FFF9684508C849EEFD7666E992D298C7060C057E28C01AF2495FF5D6073CF795285D2BED842493515391837868DF1B7456359370E2A8589E0DA96B48B68319740B7923BB8FD0349A42D643ED23FF0040CC1494CD18D9F10DEC7D523C5A66C5827C999BBA92EC52C71154D7AB7C22AB660DBD67AD30EF5DF85933D9F02C31041435FE494AB0683FCC1021DBF457B3CCFD65BC86B1F9B93B630D7D64396989ABA053AE09A22A6CF5BCEA3D25350B1E4CB7803D90C88F280BC09A91858DA6407640054D69A17341A7D03596568E7931B017D45D401BEC2CB4A2C9C89A8962BF0B328EEA083D8FF1E672CEB8E6F";
        String decrypt = MyAESUtil.decryptAES(data, "ypw5ky24f4bwmdt9zc3mece29ev9qudz".getBytes(), "d6guntxsgshnxjww");
        System.out.println(decrypt);
    }
}
